home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Tool Chest / Development Tools & Languages / Dylan Related / Mindy / Mindy 1.2 - portable sources / interp / lexer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-15  |  7.9 KB  |  349 lines  |  [TEXT/ttxt]

  1. /**********************************************************************\
  2. *
  3. *  Copyright (c) 1994  Carnegie Mellon University
  4. *  All rights reserved.
  5. *  
  6. *  Use and copying of this software and preparation of derivative
  7. *  works based on this software are permitted, including commercial
  8. *  use, provided that the following conditions are observed:
  9. *  
  10. *  1. This copyright notice must be retained in full on any copies
  11. *     and on appropriate parts of any derivative works.
  12. *  2. Documentation (paper or online) accompanying any system that
  13. *     incorporates this software, or any part of it, must acknowledge
  14. *     the contribution of the Gwydion Project at Carnegie Mellon
  15. *     University.
  16. *  
  17. *  This software is made available "as is".  Neither the authors nor
  18. *  Carnegie Mellon University make any warranty about the software,
  19. *  its performance, or its conformity to any specification.
  20. *  
  21. *  Bug reports, questions, comments, and suggestions should be sent by
  22. *  E-mail to the Internet address "gwydion-bugs@cs.cmu.edu".
  23. *
  24. ***********************************************************************
  25. *
  26. * $Header: lexer.c,v 1.1 94/10/05 21:02:33 nkramer Exp $
  27. *
  28. * This file is the lexer for the debugger.
  29. *
  30. \**********************************************************************/
  31.  
  32.  
  33.  
  34. #include "../compat/std-c.h"
  35. #include "../compat/std-os.h"
  36.  
  37. #include "mindy.h"
  38. #include "lexer.h"
  39. #include "parser.h"
  40. #include "list.h"
  41. #include "char.h"
  42. #include "str.h"
  43. #include "sym.h"
  44. #include "num.h"
  45. #include "bool.h"
  46.  
  47. #define BUFFER_SIZE    1024
  48.  
  49. FILE *yyin;
  50.  
  51. void yyinput_setter(FILE *input)
  52. {
  53.   yyin = input;
  54. }
  55.  
  56. void yyinput_clear(void)
  57. {
  58.   int c;
  59.   while ((c = getc(yyin)) != EOF && c != '\n')
  60.     ;
  61.   if (c == '\n')
  62.     ungetc(c, yyin);
  63. }
  64.  
  65. static int yyeof()
  66. {
  67.   if (errno == EINTR) {
  68.     errno = 0;
  69.     clearerr(yyin);
  70.     return 0;
  71.   } else
  72.     return -1;
  73. }
  74.  
  75. static int yygetc()
  76. {
  77.   return getc(yyin);
  78. }
  79.  
  80. static int yyungetc(int c)
  81. {
  82.   return ungetc(c, yyin);
  83. }
  84.  
  85. static int yypeekc()
  86. {
  87.   return yyungetc(yygetc());
  88. }
  89.  
  90. static int yyescape(int c)
  91. {
  92.   switch (c) {
  93.   case '\\': return '\\';
  94.   case '\'': return '\'';
  95.   case '"': return '"';
  96.   case 'a': return '\a';
  97.   case 'b': return '\b';
  98.   case 'e': return '\033';
  99.   case 'f': return '\f';
  100.   case 'n': return '\n';
  101.   case 'r': return '\r';
  102.   case 't': return '\t';
  103.   case '0': return '\0';
  104.   default: return c;
  105.   }
  106. }
  107.  
  108. static char map[] = {
  109.   /* digits => 0..9,
  110.      alphabetics => 10..35,
  111.      other symbolics => 36,
  112.      other 37
  113.      sgi <ctype.h> claimed that high ascii
  114.      had alphabetics, too, but I ignored it.
  115.    */
  116.   36,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
  117.   37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
  118.   37,36,37,37,36,36,36,37,37,37,36,36,37,36,37,36,
  119.    0, 1, 2, 3, 4, 5, 6, 7, 8, 9,37,37,36,36,36,36,
  120.   36,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
  121.   25,26,27,28,29,30,31,32,33,34,35,37,37,37,36,36,
  122.   37,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
  123.   25,26,27,28,29,30,31,32,33,34,35,37,37,37,36,37,
  124.   37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
  125.   37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
  126.   37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
  127.   37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
  128.   37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
  129.   37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
  130.   37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
  131.   37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
  132. };
  133.  
  134. static int yyisnumeric(int c, int radix)
  135. {
  136.   return map[c] < radix;
  137. }
  138.  
  139. static int yyissymbolic(int c)
  140. {
  141.   return map[c] < 37;
  142. }
  143.  
  144. static int yysymbol(int c)
  145. {
  146.   char buff[1024], *p = buff;
  147.   int keywordp = 0;
  148.  
  149.   do {
  150.     if (p == buff+sizeof(buff))
  151.       return tok_ERROR;
  152.     *p++ = c;
  153.     c = yygetc();
  154.     if (c == EOF)
  155.       return tok_ERROR;
  156.   } while (yyissymbolic(c));
  157.   if (c == ':')
  158.     keywordp = 1;
  159.   else
  160.     yyungetc(c);
  161.   *p = 0;
  162.   /* Uh, wouldn't it be better if these used # instead of $
  163.      so we couldn't be shadowing user variables? Or \ so we
  164.      couldn't shadow syntax, either? */
  165.   if (buff[0] == '$') {
  166.     if (buff[1] == 0) {
  167.       yylval = make_fixnum(-1);
  168.       return tok_DEBUGVAR;
  169.     }
  170.     if (buff[1] == '$' && buff[2] == 0) {
  171.       yylval = make_fixnum(-2);
  172.       return tok_DEBUGVAR;
  173.     }
  174.     if (buff[1] == '-' || yyisnumeric(buff[1], 10)) {
  175.       yylval = make_fixnum(strtol(buff+1, NULL, 10));
  176.       return tok_DEBUGVAR;
  177.     }
  178.     if ((buff[1] == 'a' || buff[1] == 'A')
  179.     && yyisnumeric(buff[2], 10)) {
  180.       yylval = make_fixnum(strtol(buff+2, NULL, 10));
  181.       return tok_ARG;
  182.     }
  183.   }
  184.   yylval = symbol(buff);
  185.   return keywordp ? tok_KEYWORD : tok_SYMBOL;
  186. }
  187.  
  188. static int yynumber(int c, int radix, int addressp)
  189. {
  190.   char buff[1024], *p = buff, isfloat = 0;
  191. # define append(c)    {if (p == buff+sizeof(buff)) return tok_ERROR; *p++ = c;}
  192. # define advance(c)    {c = yygetc(); if (c == EOF) return tok_ERROR;}
  193.  
  194.   if (c != '.') {
  195.     do {
  196.       append(c);
  197.       advance(c);
  198.     } while (yyisnumeric(c, radix));
  199.   }
  200.   if (radix == 10) {
  201.     if (c == '.') {
  202.       isfloat = 1;
  203.       do {
  204.     append(c);
  205.     advance(c);
  206.       } while (yyisnumeric(c, radix));
  207.     }
  208.     if (strchr("eEsSdDxX", c)) {
  209.       isfloat = c;
  210.       append('e');
  211.       advance(c);
  212.       if (c != '-' && c != '+' && ! yyisnumeric(c, radix)) {
  213.     yyungetc(c);
  214.     return tok_ERROR;
  215.       }
  216.       do {
  217.     append(c);
  218.     advance(c);
  219.       } while (yyisnumeric(c, radix));
  220.     }
  221.   }
  222.  
  223.   yyungetc(c);
  224.   append(0);
  225.  
  226.   switch (isfloat) {
  227.   case 'd': case 'D':
  228.     yylval = make_double(strtod(buff, NULL));
  229.     return tok_NUMBER;
  230.   case 1:
  231.   case 'e': case 'E':
  232.   case 's': case 'S':
  233.     yylval = make_single(strtod(buff, NULL));
  234.     return tok_NUMBER;
  235.   case 'x': case 'X':
  236.     yylval = make_extended(strtod(buff, NULL));
  237.     return tok_NUMBER;
  238.   default:
  239.     if (addressp) {
  240.       yylval =  (obj_t)strtoul(buff, NULL, radix);
  241.       return tok_ADDRESS;
  242.     } else {
  243.       yylval =  make_fixnum(strtol(buff, NULL, radix));
  244.       return tok_NUMBER;
  245.     }
  246.   }
  247. # undef append
  248. # undef advance
  249. }
  250.  
  251. static int yystring(int q, int symbolp)
  252. {
  253.   char buff[1024], *p = buff;
  254.   int c;
  255.  
  256.   while ((c = yygetc()) != EOF && c != '"') {
  257.     if (c == '\\') {
  258.       c = yygetc();
  259.       if (c == EOF)
  260.     return tok_ERROR;
  261.       else
  262.     *p++ = yyescape(c);
  263.     } else {
  264.       *p++ = c;
  265.     }
  266.     if (p == buff+sizeof(buff))
  267.       return tok_ERROR;
  268.   }
  269.   if (c == EOF)
  270.     return tok_ERROR;
  271.   *p = 0;
  272.   if (symbolp) {
  273.     yylval = symbol(buff);    /* symbol with embedded \0 how? */
  274.     return tok_KEYWORD;
  275.   } else {
  276.     yylval = alloc_byte_string(p-buff);
  277.     memcpy(string_chars(yylval), buff, p-buff);
  278.     return tok_STRING;
  279.   }
  280. }
  281.  
  282. int yylex()
  283. {
  284.   int c;
  285.  
  286.   c = yygetc();
  287.   switch (c) {
  288.   case EOF:            return yyeof() ? -1 : yylex();
  289.   case '\n':            return -1;
  290.   case ' ': case '\t':        return yylex();
  291.   case '(':            return tok_LPAREN;
  292.   case ')':            return tok_RPAREN;
  293.   case ',':            return tok_COMMA;
  294.   case '#':
  295.     c = yygetc();
  296.     switch (c) {
  297.     case 't': case 'T':            return tok_TRUE;
  298.     case 'f': case 'F':            return tok_FALSE;
  299.     case 'b': case 'B':            return yynumber(yygetc(), 2, 0);
  300.     case 'o': case 'O':            return yynumber(yygetc(), 8, 0);
  301.     case 'x': case 'X':            return yynumber(yygetc(), 16, 0);
  302.     case '"':                return yystring(c, 1);
  303.     default:
  304.       yyungetc(c);
  305.       return tok_ERROR;
  306.     }
  307.   case '"':            return yystring(c, 0);
  308.   case '\'':
  309.     c = yygetc();
  310.     if (c == '\\') {
  311.       c = yygetc();
  312.       if (c == EOF)
  313.     return tok_ERROR;
  314.       else
  315.     yylval = int_char(yyescape(c));
  316.     } else {
  317.       yylval = int_char(c);
  318.     }
  319.     if (yygetc() != '\'')
  320.       return tok_ERROR;
  321.     else
  322.       return tok_CHARACTER;
  323.  
  324.   case '.':
  325.     if (yyisnumeric(yypeekc(), 10))
  326.       return yynumber(c, 10, 0);
  327.     return tok_ERROR;
  328.  
  329.   case '-': case '+':
  330.     if (yyisnumeric(yypeekc(), 10))
  331.       return yynumber(c, 10, 0);
  332.     return yysymbol(c);
  333.  
  334.   case '0':
  335.     c = yygetc();
  336.     if (c == 'x' || c == 'X')
  337.       return yynumber(yygetc(), 16, 1);
  338.     yyungetc(c);
  339.     return yynumber('0', 10, 0);
  340.  
  341.   default:
  342.     if (yyisnumeric(c, 10))
  343.       return yynumber(c, 10, 0);
  344.     if (yyissymbolic(c))
  345.       return yysymbol(c);
  346.     return tok_ERROR;
  347.   }
  348. }
  349.